package com.ytt.core.api.controller.token;

import com.ytt.core.api.security.CurrentUser;
import com.ytt.core.model.security.token.JwtTokenDTO;
import com.ytt.core.model.security.token.UserLoginInfoDTO;
import com.ytt.core.service.exception.NoSuchDataException;
import com.ytt.core.service.service.user.UserService;
import com.ytt.core.util.jwt.JwtTokenUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

/**
 * TokenController
 *
 * @author chenwen
 * @date 2019/9/12 14:42
 */
@Api(tags = {"令牌管理"})
@RestController
@RequestMapping("/api/token")
@Validated
public class TokenController {
    private final UserService userService;
    private final AuthenticationManager authenticationManager;
    private JwtTokenUtil jwtTokenUtil = new JwtTokenUtil();

    public TokenController(UserService userService, AuthenticationManager authenticationManager) {
        this.userService = userService;
        this.authenticationManager = authenticationManager;
    }

    @ApiOperation(value = "使用用户账号和密码生成访问令牌")
    @PostMapping("")
    public JwtTokenDTO generateToken(@ApiParam(value = "登录信息", required = true) @RequestBody @Validated UserLoginInfoDTO loginInfo, HttpServletRequest request){
        UsernamePasswordAuthenticationToken principal = new UsernamePasswordAuthenticationToken(
                loginInfo.getAccount(),
                loginInfo.getPassword());
        principal.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        String userId = null;

        try {
            userId = userService.findByAccount(loginInfo.getAccount());
            Authentication authentication = authenticationManager.authenticate(principal);
            SecurityContextHolder.getContext().setAuthentication(authentication);
            CurrentUser currentUser = (CurrentUser) (SecurityContextHolder.getContext().getAuthentication().getPrincipal());
            String token = jwtTokenUtil.generateToken(userId, currentUser.getUsername());
            return createJwtTokenDto(userId, currentUser.getUsername(), token);
        } catch (NoSuchDataException e) {
            // 为安全起见，不直接提示用户名不存在
            throw new BadCredentialsException("no such account");
        } catch (BadCredentialsException e) {
            throw e;
        }
    }



    /**
     * 组装 JwtTokenDTO
     *
     * @param userId   用户id
     * @param userName 用户名称
     * @param token    token
     * @return JwtTokenDTO
     */
    private JwtTokenDTO createJwtTokenDto(String userId, String userName, String token) {
        JwtTokenDTO userToken = new JwtTokenDTO();
        userToken.setUserId(userId);
        userToken.setUserName(userName);
        userToken.setIssued(jwtTokenUtil.getIssueDateFromToken(token));
        userToken.setExpires(jwtTokenUtil.getExpirationDateFromToken(token));
        userToken.setToken(token);
        return userToken;
    }
}
